package org.psyduck.controller.security;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.psyduck.admin.dict.service.DictService;
import org.psyduck.admin.user.service.UserService;
import org.psyduck.common.constant.Constants;
import org.psyduck.common.exception.BusinessException;
import org.psyduck.common.model.JsonBean;
import org.psyduck.common.model.JsonCode;
import org.psyduck.security.model.User;
import org.psyduck.security.providers.SmsAuthenticationProvider;
import org.psyduck.security.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping("security")
public class SecurityController {

    @Value("${jwt.header}")
    private String tokenHeader;

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    SmsAuthenticationProvider smsAuthenticationProvider;

    @Autowired
    JwtUtils jwtUtils;

    @Autowired
    DictService dictService;

    @Autowired
    UserService userService;

    private Authentication authenticate(String username, String password) {
        try {
            //该方法会去调用userDetailsService.loadUserByUsername()去验证用户名和密码，如果正确，则存储该用户名密码到“security 的 context中”
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (InternalAuthenticationServiceException | DisabledException | BadCredentialsException e) {
            throw new BusinessException(JsonCode.LOGIN_ERROR,e.getMessage());
        }
    }

    public String putToken(Authentication authentication){
        //存储认证信息
        SecurityContextHolder.getContext().setAuthentication(authentication);
        //生成token
        User userDetail = (User) authentication.getPrincipal();
        String token = jwtUtils.generateAccessToken(userDetail);
        //存储token
        jwtUtils.putToken(token);
        return token;
    }

    @RequestMapping("phoneLogin")
    public String phoneLogin(String phone, String code){
        validUser(phone);
        return putToken(smsAuthenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(phone, code)));
    }

    @PostMapping("login")
    public String login(@RequestBody User user, HttpServletRequest request){
        validUser(user.getUsername());
        return putToken(authenticate(user.getUsername(), user.getPassword()));
    }

    public void validUser(String username){
        User userOne = userService.getOne(new QueryWrapper<User>().eq("username", username).eq("is_del", Constants.NOT_DELETE));
        if(null != userOne && userOne.getIsLogin() == 1){
            throw new BusinessException(JsonCode.USER_LOCK,null);
        }
    }

    @GetMapping("/logout")
    public JsonBean logout(HttpServletRequest request){
        String token = request.getHeader(tokenHeader);
        if (StrUtil.isNotBlank(token) && !token.equals("undefined")) {
            jwtUtils.deleteToken(jwtUtils.getUsernameFromToken(token));
        }
        return JsonBean.success();
    }

    @GetMapping("validateToken")
    public boolean validateToken(String token){
        String username = jwtUtils.getUsernameFromToken(token);
        if (!(jwtUtils.containToken(token))) {
            return false;
        }
        return true;
    }

//    @GetMapping("resetToken")
//    public String resetToken(HttpServletRequest request){
//        String token = request.getHeader(tokenHeader);
//        String username = jwtUtils.getUsernameFromToken(token);
//        User userDetail = userService.getDao().getUserByUsername(username);
//        if (jwtUtils.canTokenBeRefreshed(token, new Date())){
//            token =  jwtUtils.refreshToken(token);
//            return token;
//        }
//        return null;
//    }

}
